using System;
using Microsoft.SPOT;

namespace A6281 {
	public class ChipColorSequence : ICyclicEnumerable {
		public ChipColorSequence( params ChipColorSet[] chipColorSetArray ) {
			lock( this.chipColorSetArraySync ) {
				this.chipColorSetArray = chipColorSetArray;
			}
		}

		public System.Collections.IEnumerator GetEnumerator() {
			return new ChipColorSequenceCyclicEnumerator( this );
		}

		public ChipColorSet GetChipColorByIndex( uint index ) {
			lock( this.chipColorSetArraySync ) {
				return this.chipColorSetArray[ index ];
			}
		}

		public uint GetChipColorLength() {
			lock( this.chipColorSetArraySync ) {
				return ( uint )this.chipColorSetArray.Length;
			}
		}

		internal class ChipColorSequenceCyclicEnumerator : ICyclicEnumerator {
			public ChipColorSequenceCyclicEnumerator( ChipColorSequence mother ) {
				this.mother = mother;
			}

			public object Current {
				get {
					lock( this.indexSync ) {
						return this.mother.GetChipColorByIndex( this.index );
					}
				}
			}

			public bool MoveNext() {
				lock( this.indexSync ) {
					this.index = ( this.index + 1 ) % this.mother.GetChipColorLength();
				}
				return true;
			}

			public void Reset() {
				lock( this.indexSync ) {
					this.index = 0;
				}
			}

			protected ChipColorSequence mother;
			protected object indexSync = new object();
			protected uint index;
		}

		protected object chipColorSetArraySync = new object();
		protected ChipColorSet[] chipColorSetArray;

		public static ChipColorSequence CreateRainbow( ) {
			ChipColor[] rainbowColors = new ChipColor[] { 
				ChipColor.FromRGB( 0xFF, 0x00, 0x00 ),
				ChipColor.FromRGB( 0xFF, 0xA5, 0x00 ),
				ChipColor.FromRGB( 0xFF, 0xFF, 0x00 ),
				ChipColor.FromRGB( 0x00, 0x80, 0x00 ),
				ChipColor.FromRGB( 0x00, 0x00, 0xFF ),
				ChipColor.FromRGB( 0x4B, 0x00, 0x82 ),
				ChipColor.FromRGB( 0xEE, 0x82, 0xEE )
			};

			return new ChipColorSequence(
				new ChipColorSet( 0, rainbowColors ),
				new ChipColorSet( 1, rainbowColors ),
				new ChipColorSet( 2, rainbowColors ),
				new ChipColorSet( 3, rainbowColors ),
				new ChipColorSet( 4, rainbowColors ),
				new ChipColorSet( 5, rainbowColors ),
				new ChipColorSet( 6, rainbowColors ) );

		}

		public static ChipColorSequence CreateXmas() {
			return new ChipColorSequence( new ChipColorSet( ChipColor.PureRed, ChipColor.PureGreen ),
											new ChipColorSet( ChipColor.PureGreen, ChipColor.PureRed ) );
		}

		public static ChipColorSequence CreateRGB() {
			return new ChipColorSequence( 
					new ChipColorSet( ChipColor.PureRed, ChipColor.PureGreen, ChipColor.PureBlue ),
					new ChipColorSet( ChipColor.PureGreen, ChipColor.PureBlue, ChipColor.PureRed ),
					new ChipColorSet( ChipColor.PureBlue, ChipColor.PureRed, ChipColor.PureGreen )
					);
		}

		public static ChipColorSequence CreateCylon( int length, ChipColor scanColor, ChipColor backgroundColor ) {

			// | | | | | | | | | x = 8
			//  0 1 2 3 4 5 6 7
			//	0-7-0
			// ( x * 2 ) - 1
			// 0 -> x - 1 -> 0

			ChipColor[] cylonColors = new ChipColor[ length ];
			cylonColors[ 0 ] = scanColor.Clone();
			for ( int index = 1; index < cylonColors.Length; index++ ) {
				cylonColors[ index ] = backgroundColor.Clone();
			}

			ChipColorSet[] cylonSets = new ChipColorSet[ ( length * 2 ) - 2 ];
			int setIndex = 0;
			uint colorIndex = 0;

			for ( ; colorIndex < length; colorIndex++, setIndex++ ) {
				cylonSets[ setIndex ] = new ChipColorSet( colorIndex, cylonColors );
			}
			for ( colorIndex-=2; colorIndex > 0; colorIndex--, setIndex++ ) {
				cylonSets[ setIndex ] = new ChipColorSet( colorIndex, cylonColors );
			}

			return new ChipColorSequence( cylonSets );
		}
	}
}
